﻿// Copyright (c) Vitaly Kamiansky. All rights reserved. 
// See License.txt in the project root.

using System;
using System.ComponentModel;
using System.Threading;

namespace Property.Workers
{
    public class TimeoutFunctionWorkerDecorator<T> : FunctionWorkerDecorator<T>
    {
        protected TimeoutFunctionWorkerDecorator(IFunctionWorkerPrototype<T> compositionBasePrototype, 
            Func<T> getValue, ITimerPrototype timerPrototype)
            : base(compositionBasePrototype, getValue)
        {
            if (timerPrototype == null) throw new ArgumentNullException("timerPrototype");

            _Timer = timerPrototype.Create();

            if (_Timer == null) throw new NotSupportedException(StringsCallbacks.CANT_OBTAIN_TIMER);

            _Timer.Tick += TimeIsUp;
        }

        //=//

        private readonly ITimer _Timer;

        private bool TooLateState;

        public override void RunWorkerAsync()
        {
            TooLateState = false;
            _Timer.Stop();
            _Timer.Start();
            _CompositionBase.RunWorkerAsync();
        }

        void TimeIsUp(object sender, EventArgs e)
        {
            TooLateState = true;
            _Timer.Stop();
            OnRunWorkerCompleted(new RunWorkerCompletedEventArgs(default(T), new TimeoutException(), false));
        }

        protected override void Completed(object sender, RunWorkerCompletedEventArgs e)
        {
            _Timer.Stop();
            if (!TooLateState) OnRunWorkerCompleted(e);
        }

        public override void Dispose()
        {
            _Timer.Tick -= TimeIsUp;
            _Timer.Dispose();
            base.Dispose();
        }
    }
}
